package com.llbnk.common.exception;

import com.llbnk.common.result.R;
import com.llbnk.common.result.ResponseEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;


/**
 * @author shkstart
 * @create 2022-04-08 10:20
 */
//因为程序core启动的时候需要加载common 所以需要在启动类上面Scan这个包！！！
@Slf4j//添加日志打印
//想要以json字符串的形式返回给前端RestController注解
@RestControllerAdvice//如果项目中有错误 马上就会跳到这个页面来处理  AOP切面原理（切面编程）
public class UnifiedExceptionHandler {
    @ExceptionHandler(value = Exception.class)
    //添加ExceptionHandler注解 当发生异常(Exception这个地方是value的值)自动调用
    public R handleException(Exception e){//捕获所有controller mapper service中的所有异常
        log.error(e.getMessage(),e);
        return R.error();//调用的R中的错误处理
    }


    @ExceptionHandler(value = BadSqlGrammarException.class)
    //添加ExceptionHandler注解 当发生异常(Exception这个地方是value的值)自动调用
    public R handleException(BadSqlGrammarException e){//捕获所有controller mapper service中的所有异常
        log.error(e.getMessage(),e);
        return R.setResult(ResponseEnum.BAD_SQL_GRAMMAR_ERROR);//调用的R中的错误处理
    }

    /**
     * 自定义异常
     * 首先先在controller的方法中throw异常，这个异常就是BusinessException（有许多重载构造器）
     * throw自定义异常之后就会在UnifiedExceptionHandler这个类中进行捕获，然后来处理这个异常
     */
    @ExceptionHandler(value = BusinessException.class)
    public R handleBusinessException(BusinessException e){
        log.error(e.getMessage(), e);
        return R.error().message(e.getMessage()).code(e.getCode());
    }

    //专门针对前端可能发生的各种异常还没到后端就已经错误了，这种叫Controller上层异常
    @ExceptionHandler({
            NoHandlerFoundException.class,
            HttpRequestMethodNotSupportedException.class,
            HttpMediaTypeNotSupportedException.class,
            MissingPathVariableException.class,
            MissingServletRequestParameterException.class,
            TypeMismatchException.class,
            HttpMessageNotReadableException.class,
            HttpMessageNotWritableException.class,
            MethodArgumentNotValidException.class,
            HttpMediaTypeNotAcceptableException.class,
            ServletRequestBindingException.class,
            ConversionNotSupportedException.class,
            MissingServletRequestPartException.class,
            AsyncRequestTimeoutException.class
    })
    public R handleServletException(Exception e) {
        log.error(e.getMessage(), e);
        //SERVLET_ERROR(-102, "servlet请求异常"),
        return R.error()
                .message(ResponseEnum.SERVLET_ERROR.getMessage())
                .code(ResponseEnum.SERVLET_ERROR.getCode());
    }
}
